/*
 * @Description:
 * @Version: 2.0
 * @Autor: jl.g
 * @Date: 2023-05-27 21:02:31
 * @LastEditors: jinglin.gao
 * @LastEditTime: 2023-11-20 22:27:08
 */
import React, { useRef, useState, useEffect } from "react";
import {
  Input,
  Image,
  Button,
  Progress,
  Pagination,
  Tooltip,
  Popconfirm,
  Modal,
} from "antd";
import {
  CopyOutlined,
  CloseOutlined,
  CloudDownloadOutlined,
  DeleteOutlined,
  RotateRightOutlined,
  RotateLeftOutlined,
} from "@ant-design/icons";
import { useHistory } from "react-router-dom";
import Marquee from "react-fast-marquee";
import MjLoading from "@/components/MjLoading";
import {
  getImageList,
  generateImgFn,
  getImageTaskState,
  changeGenerateImg,
  deleteMjGenerateImg,
  publishState,
} from "@/api/midjourney";
import { accountChangeAction } from "@/store/actions/home_action";
import { useDispatch, useSelector } from "react-redux";
import { transformImgState } from "../utils";
import { messageFn, copyToClipboardFn, downloadImage } from "@/utils";
import _ from "lodash";
import { productConsumedTypeConfig } from "@/api/user";
import MjGenerateSetting from "../components/mjGenerateSetting";
import generateImgFail from "../../../../public/assets/imgs/generateImgFail.svg";
import arrow from "../../../../public/assets/imgs/arrow.svg";
import mjNoDataImg from "../../../../public/assets/imgs/mjNoDataImg.svg";
import styles from "./index.module.less";
const { confirm } = Modal;

const MjGenerate = () => {
  const history = useHistory();
  const dispatch = useDispatch();
  const [productInfo, setProductInfo] = useState("");

  // 获取商品消耗提示语字典
  const consumptionPrompt = useSelector((state) => state.consumptionPrompt);

  // 账户信息
  const accountInfo = useSelector((state) => state.accountInfo);
  console.log(accountInfo, "accountInfoaccountInfo");

  // 图片目前又三种情况
  // UPSCALE 单个图片放大
  // VARIATION 选择其中一种图片生成四张
  // IMAGINE 通过关键次生成

  // 生成图片对象
  const promptObj = useRef({
    prompt: "",
    base64: "",
  });

  const [userPrompt, setUserPrompt] = useState("");

  // 生成图片尺寸
  const generateImgSize = useRef({
    label: "1:1",
    id: 1,
    value: " --ar 1:1",
  });

  // 选择模型
  const generateImgModel = useRef({
    id: 0,
    title: "MJ",
    info: "通用写实风格MJ",
    value: "",
  });

  // 分页
  const [pagination, setPagination] = useState({
    total: 0,
    size: 6,
    current: 1,
  });

  // 任务状态查询定时器
  const genearteImgTaskTimer = useRef([]);

  // 定时器调用时间

  const timeOut = useRef(10 * 1000);
  // 生成图片列表
  const [generateImgList, setGenerateImgList] = useState([]);
  const generateImgListRef = useRef(null);
  // 编写提示词
  const setPrompt = (e) => {
    promptObj.current.prompt = e.target.value;
    setUserPrompt(e.target.value);
  };

  // 移动端兼容 打开配置
  // 0关闭 1 打开
  const [mobileConfigState, setMobileConfigState] = useState(0);

  // 删除已经绘制好的图
  const deleteMjGenerateImgFn = async (id) => {
    try {
      let res = await deleteMjGenerateImg(id);
      if (res.code === 200) {
        messageFn({
          type: "success",
          content: "删除成功",
        });
        getImageListFn();
      } else {
        messageFn({
          type: "error",
          content: res.message,
        });
      }
    } catch (error) {
      console.log(error);
    }
  };

  // 图片下载
  const downloadImageFn = (v) => {
    let url = `/api/download/image?fileId=${v.fileId}&type=2`;
    messageFn({
      type: "success",
      content: "下载成功,请稍后",
    });
    downloadImage(url);
  };

  // 获取已经生成的图片列表
  const getImageListFn = async (current) => {
    try {
      let data = {
        size: pagination.size,
        current: current || pagination.current,
      };
      let res = await getImageList(data);
      if (res.code === 200) {
        let resData = res.result.records || [];

        // 设置总条数
        setPagination({
          ...pagination,
          total: res.result.total,
        });
        setGenerateImgList(resData);
        generateImgListRef.current = resData;

        // 每次查询数据需要清空所有的轮询数据
        genearteImgTaskTimer.current.forEach((v) => {
          if (v.timer) {
            clearInterval(v.timer);
          }
        });
        // 清空任务队列
        genearteImgTaskTimer.current = [];
        // 查询列表中是否有未完成的任务
        // 如果有则加入任务队列开始查询任务

        // 默认任务状态
        resData.forEach((v) => {
          if (!v.fileStatus) {
            v.fileStatus = "NOT_START";
          }
        });
        resData.forEach((v) => {
          if (
            v.fileStatus === "NOT_START" ||
            v.fileStatus === "SUBMITTED" ||
            v.fileStatus === "IN_PROGRESS"
          ) {
            console.log("执行了执行了");
            addTaskToTimerTask(v.fileId);
            // 查询任务状态
            getGenearteImgTaskState(v.fileId);
          }
        });
      }
    } catch (error) {
      console.log(error);
    }
  };

  /**
   * @description: 生成图片
   * @return {*}
   * @author: jl.g
   */
  const generateImg = async () => {
    if (!userPrompt) {
      messageFn({
        type: "error",
        content: "咒语不能为空",
      });

      return;
    }

    setUserPrompt("");

    // 跳转回第一页
    setPagination({
      ...pagination,
      current: 1,
    });

    try {
      let data = _.cloneDeep(promptObj.current);
      // 如果手动指定了图片大小 则无需走图片配置
      if (data.prompt.indexOf("--ar") === -1) {
        data.prompt = data.prompt + generateImgSize.current.value;
      }

      // 二次元风格
      if (data.prompt.indexOf("--niji") === -1) {
        data.prompt = data.prompt + generateImgModel.current.value;
      }

      let res = await generateImgFn(data);
      if (res.code === 200) {
        messageFn({
          type: "success",
          content: "任务创建成功,正在拼命绘制中,请耐心等候。",
        });
        getImageListFn(1);

        // 扣除账户余额
        dispatch(
          accountChangeAction(new Date().getTime() + "_" + Math.random())
        );
      } else if (res.code === 4003) {
        // 余额不足
        confirm({
          title: "余额不足",
          content: "尊敬的用户您好,您的账户余额不足，点击确定购买商品。",
          onOk() {
            history.replace("/ai/commodity");
          },
        });
      } else {
        messageFn({
          type: "error",
          content: res.message,
        });
      }
    } catch (error) {
      console.log(error);
    }
  };

  // 向任务队列添加任务
  const addTaskToTimerTask = (fileId) => {
    genearteImgTaskTimer.current.push({
      fileId,
      timer: null,
      // 创建时间
      createTime: new Date().getTime(),
    });
  };

  // 定时查询任务状态
  const getGenearteImgTaskState = (fileId) => {
    //  每3S查询一下当前任务的状态
    // 支持多个绘画任务并发地计算状态
    genearteImgTaskTimer.current.forEach((v) => {
      if (v.fileId === fileId) {
        v.timer = setInterval(() => {
          getImageTaskStateFn(fileId);
        }, timeOut.current);
      }
    });
  };

  // 发布到广场
  const publishStateFn = async (itemData, state) => {
    try {
      let data = {
        fileId: itemData.fileId,
        publishState: state,
      };
      let res = await publishState(data);
      if (res.code === 200) {
        messageFn({
          type: "success",
          content: "操作成功",
        });
        getImageListFn();
      } else {
        messageFn({
          type: "error",
          content: "操作失败",
        });
      }
    } catch (error) {
      console.log(error);
    }
  };

  // 当某个任务调用成功删除对应的轮询调用
  const clearTimerTask = (fileId) => {
    console.log(genearteImgTaskTimer.current, "clearTimerTaskclearTimerTask");
    if (genearteImgTaskTimer.current.length) {
      // 找到对应的任务
      let activeIndex = null;
      genearteImgTaskTimer.current.forEach((v, index) => {
        if (v.fileId === fileId) {
          clearInterval(v.timer);
          activeIndex = index;
        }
      });

      console.log(activeIndex, "待删除的项");
      if (activeIndex !== null) {
        // 从任务列表删除任务
        genearteImgTaskTimer.current.splice(activeIndex, 1);
      }
    }
  };

  // 查询生成任务状态
  const getImageTaskStateFn = async (fileId) => {
    try {
      let params = {
        fileId,
      };
      let res = await getImageTaskState(params);
      if (res.code === 200) {
        let resData = res.result;
        // 查询当前需要更改状态的任务
        let generateImgListCopy = _.cloneDeep(generateImgListRef.current);

        // 查询正在执行中的任务
        let findInProgressTaskIndex = generateImgListCopy.findIndex(
          (v) => v.fileId === fileId
        );
        // 每次将当前带生成任务的状态修改
        generateImgListCopy.splice(findInProgressTaskIndex, 1, resData);

        setGenerateImgList([...generateImgListCopy]);
        generateImgListRef.current = [...generateImgListCopy];

        console.log(resData.fileStatus, "fileStatusfileStatus");
        console.log(fileId, "fileIdfileIdfileId");
        console.log(genearteImgTaskTimer.current, "任务");
        if (
          resData.fileStatus === "SUCCESS" ||
          resData.fileStatus === "FAILURE"
        ) {
          // 清除对应任务
          clearTimerTask(fileId);
        }
      } else {
        // 清除对应任务
        clearTimerTask(fileId);
        messageFn({
          type: "error",
          content: res.message,
        });
      }
    } catch (error) {
      console.log(error);
    }
  };

  // 生成图片微调
  const changeGenerateImgFn = async (itemData, type, index) => {
    try {
      let data = {
        fileId: itemData.fileId,
        action: type,
        index: index + 1,
      };

      let res = await changeGenerateImg(data);
      if (res.code === 200) {
        messageFn({
          type: "success",
          content: "操作成功,请耐心等候",
        });
        getImageListFn(1);
      } else if (res.code === 4003) {
        // 余额不足
        confirm({
          title: "余额不足",
          content: "尊敬的用户您好,您的账户余额不足，点击确定购买商品。",
          onOk() {
            history.replace("/ai/commodity");
          },
        });
      } else {
        messageFn({
          type: "error",
          content: res.message || "操作失败,请稍后再试",
        });
      }
    } catch (error) {
      console.log(error);
    }
  };

  // 分页变化
  const onPaginationChange = (page, pageSize) => {
    setPagination({
      ...pagination,
      size: pageSize,
      current: page,
    });
  };

  // 获取商品消耗提示
  const getProductConsumedTypeConfig = async () => {
    try {
      let params = {
        productType: 3,
      };
      let res = await productConsumedTypeConfig(params);
      if (res.code === 200) {
        setProductInfo(res.result);
        // dispatch(consumptionPromptAction(res.result));
      }
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    getImageListFn();

    return () => {
      if (genearteImgTaskTimer.current.length) {
        genearteImgTaskTimer.current.forEach((v) => {
          clearInterval(v.timer);
        });
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pagination.size, pagination.current]);

  useEffect(() => {
    if (genearteImgTaskTimer.current.length) {
      genearteImgTaskTimer.current.forEach((v) => {
        clearInterval(v.timer);
      });
    }

    getProductConsumedTypeConfig();
  }, []);
  return (
    <div className={styles.mjGenerate}>
      <div className="mj-generate_content">
        <div className="mj_content-head-info">
          {/* <div className="marquessBox">
            <Marquee pauseOnHover={true} speed={30} loop={0}>
              <div className="info" title={productInfo}>
                {productInfo}
              </div>
            </Marquee>
          </div> */}

          <div className="mj_balance">
            剩余绘画次数:{accountInfo?.mjBalance || 0}
          </div>
        </div>
        <div className="mj-content_head">
          <div className="mj_head-tools">
            <Input.TextArea
              rows={2}
              maxLength={300}
              onChange={setPrompt}
              value={userPrompt}
              className="mj_head-tools-input"
              placeholder="请输入咒语"
              resize="none"
            />
            <span
              onClick={_.debounce(generateImg, 500)}
              className="mj_head-tools-btn"
            >
              生成
            </span>
          </div>
          <div
            className="mj_head-settings"
            onClick={() => setMobileConfigState(1)}
          >
            <span className="label">展开配置</span>
            <img className="img" src={arrow} alt="" />
          </div>
        </div>

        <div className="mj-content_warp">
          {generateImgList.length
            ? generateImgList.map((v) => (
                <div key={v.fileId} className="mj-generate_info">
                  {v.fileStatus === "SUCCESS" ? (
                    <>
                      <div className="mj-generate_info_warp">
                        <div className="mj-content-item">
                          <div className="mj-content-item_tools">
                            <div className="mj-generate-img-state">
                              {transformImgState(v.fileStatus)}
                            </div>

                            <div className="tools">
                              <Tooltip placement="right" title={v.filePrompt}>
                                <Button
                                  style={{ marginRight: 5 }}
                                  type="primary"
                                  onClick={() =>
                                    copyToClipboardFn(v.filePrompt, "复制成功")
                                  }
                                  className="mj-generate-tools_btn"
                                  icon={<CopyOutlined />}
                                  size="small"
                                >
                                  咒语
                                </Button>
                              </Tooltip>

                              <Button
                                style={{ marginRight: 5 }}
                                onClick={() => downloadImageFn(v,2)}
                                className="mj-generate-tools_btn"
                                icon={<CloudDownloadOutlined />}
                                size="small"
                                type="primary"
                              >
                                下载
                              </Button>
                              {v.fileAction === "UPSCALE" ? (
                                <>
                                  {v.publishState === "NOT_PUBLISH" ? (
                                    <Button
                                      onClick={() =>
                                        publishStateFn(v, "PUBLISHED")
                                      }
                                      className="mj-generate-tools_btn"
                                      icon={<RotateRightOutlined />}
                                      size="small"
                                      type="primary"
                                    >
                                      发布
                                    </Button>
                                  ) : (
                                    <Button
                                      onClick={() =>
                                        publishStateFn(v, "NOT_PUBLISH")
                                      }
                                      className="mj-generate-tools_btn"
                                      icon={<RotateLeftOutlined />}
                                      size="small"
                                      danger
                                    >
                                      取消发布
                                    </Button>
                                  )}
                                </>
                              ) : (
                                ""
                              )}

                              <Popconfirm
                                title="数据删除后不可恢复,是否确认删除?"
                                okText="确认"
                                cancelText="取消"
                                onConfirm={() =>
                                  deleteMjGenerateImgFn(v.fileId)
                                }
                              >
                                <Button
                                  size="small"
                                  className="deleteImg"
                                  icon={<DeleteOutlined />}
                                  danger
                                >
                                  删除
                                </Button>
                              </Popconfirm>
                            </div>
                          </div>

                          <div
                            className={`mj-generate_img ${
                              v.fileAction === "UPSCALE"
                                ? "mj-generate_img_upscale"
                                : ""
                            }`}
                          >
                            <Image
                              width={320}
                              height={v.fileAction === "UPSCALE" ? 365 : 320}
                              src={v.cosUrl}
                              alt=""
                            />
                          </div>
                        </div>
                      </div>

                      <div className="mj-content-bottom_tools">
                        {v.fileAction !== "UPSCALE" ? (
                          <div className="mj-content-bottom_config">
                            <div className="mj-content-bottom_config_U">
                              <span className="mj-item_bottom_U_label">
                                放大:
                              </span>

                              <div className="mj-item_bottom_U_btns">
                                {new Array(4).fill(null).map((item, index) => (
                                  <span
                                    key={index}
                                    onClick={_.debounce(
                                      () =>
                                        changeGenerateImgFn(
                                          v,
                                          "UPSCALE",
                                          index
                                        ),
                                      500
                                    )}
                                    className="mj-item_bottom_U_btns_item"
                                  >
                                    图{index + 1}
                                  </span>
                                ))}
                              </div>
                            </div>

                            <div className="mj-content-bottom_config_U">
                              <span className="mj-item_bottom_U_label">
                                生成:
                              </span>

                              <div className="mj-item_bottom_U_btns">
                                {new Array(4).fill(null).map((item, index) => (
                                  <span
                                    key={index}
                                    onClick={_.debounce(
                                      () =>
                                        changeGenerateImgFn(
                                          v,
                                          "VARIATION",
                                          index
                                        ),
                                      500
                                    )}
                                    className="mj-item_bottom_U_btns_item"
                                  >
                                    图{index + 1}
                                  </span>
                                ))}
                              </div>
                            </div>
                          </div>
                        ) : (
                          ""
                        )}

                        <div className="mj-content-bottom_info">
                          时间:{v.createTime}
                        </div>
                      </div>
                    </>
                  ) : (
                    <div className="mj-content-item">
                      <div className="mj-content-item_tools">
                        <div
                          className={`mj-generate-img-state ${
                            v.fileStatus === "FAILURE" ||
                            v.fileStatus === "EXPIRE"
                              ? "mj-generate-img-failure"
                              : ""
                          }`}
                        >
                          {transformImgState(v.fileStatus)}
                        </div>

                        {/* 只有成功和失败状态 才可以进行删除 */}
                        {v.fileStatus === "FAILURE" ? (
                          <div className="tools">
                            <Popconfirm
                              className="deleteImg"
                              title="数据删除后不可恢复,是否确认删除?"
                              okText="确认"
                              cancelText="取消"
                              onConfirm={() => deleteMjGenerateImgFn(v.fileId)}
                            >
                              <Button
                                icon={<DeleteOutlined />}
                                danger
                                size="small"
                              >
                                删除
                              </Button>
                            </Popconfirm>
                          </div>
                        ) : (
                          ""
                        )}
                      </div>

                      <div className="mj-generate_img">
                        {v.fileStatus === "FAILURE" ? (
                          <div className="mj-generate_img_loadingBox">
                            <img
                              className="generateImgFail"
                              src={generateImgFail}
                              alt=""
                            />
                          </div>
                        ) : (
                          <div className="mj-generate_img_loadingBox">
                            <div className="mj-generate_img_loading">
                              <MjLoading></MjLoading>
                              <p className="mj-generate_img_loading_label">
                                生成中预计耗时60s,请耐心等候。
                              </p>

                              <Progress
                                type="circle"
                                percent={Number(v.progress.replace("%", ""))}
                                strokeColor={{
                                  "0%": "#108ee9",
                                  "100%": "#87d068",
                                }}
                              />
                            </div>
                          </div>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              ))
            : ""}
        </div>

        {generateImgList.length === 0 ? (
          <div className="mj_content-nodeData-box">
            <img className="mj_content-nodeData-img" src={mjNoDataImg} alt="" />
            <p className="mj_content-nodeData-info">
              当前您尚未进行图像绘制,快输入描述进行图像创作吧!
            </p>
          </div>
        ) : (
          ""
        )}
        {pagination.total > 6 ? (
          <Pagination
            className="mj_content-bottom-pagination"
            pageSizeOptions={[6, 12, 18, 24]}
            style={{ float: "right" }}
            onChange={onPaginationChange}
            current={pagination.current}
            pageSize={pagination.size}
            showSizeChanger
            total={pagination.total}
          ></Pagination>
        ) : (
          ""
        )}
      </div>
      {/* 移动端遮罩层 */}
      {mobileConfigState === 1 ? (
        <div
          className="mobile_mask"
          onClick={() => setMobileConfigState(0)}
        ></div>
      ) : (
        ""
      )}

      <div
        className={`mj-generate_setting ${
          mobileConfigState === 1 ? "mobileSettingShow" : ""
        }`}
      >
        <div className="title-box">
          <span className="label">配置详情</span>
          <CloseOutlined
            onClick={() => setMobileConfigState(0)}
          ></CloseOutlined>
        </div>
        <MjGenerateSetting
          generateImgModel={generateImgModel}
          generateImgSize={generateImgSize}
          promptObj={promptObj}
        ></MjGenerateSetting>
      </div>
    </div>
  );
};

export default MjGenerate;
